package org.popupcommunication.controller;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.popupcommunication.dao.GroupDAO;
import org.popupcommunication.dao.UserDAO;
import org.popupcommunication.model.Group;
import org.popupcommunication.model.Message;
import org.popupcommunication.model.User;
import org.popupcommunication.service.GroupManager;
import org.popupcommunication.service.MessageManager;
import org.popupcommunication.service.UserManager;
import org.popupcommunication.utils.Email;
import org.popupcommunication.utils.FileUtil;
import org.popupcommunication.web.UserFormAdmin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomCollectionEditor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("admin/utilisateur")
public class AdminUserController {
	@Autowired
	UserManager userService;
	@Autowired
	GroupManager groupService;
	@Autowired
	UserDAO userRepository;
	@Autowired
	GroupDAO groupRepository;
	@Autowired
	MessageManager messageService;

	Map<Integer, Group> groupeCache;
	List<Group> lstGrp;

	public UserManager getUserService() {
		return userService;
	}

	public void setUserService(UserManager userService) {
		this.userService = userService;

	}

	private static final String form_ajout = "users/ajouterUser";
	private static final String form_edit = "admin/users/editerUser";
	private static final String list_users = "admin/users/listUsers";
	private static final String valid_user = "admin/users/validerUser";
	private static final String list_users_validation = "admin/users/listUsersWaiting";
	private static final String db_ajout_confirm = "users/confirmationAjout";
	private static final String db_modif_confirm = "users/confirmationModif";

	@InitBinder
	public void initBinder(WebDataBinder binder) {
		binder.setAllowedFields(new String[] { "firstName", "lastName",
				"password", "email", "confirmEmail", "confirmPassword",
				"fonction", "institution", "tel", "gsm", "isAdmin",
				"listGroup", "idUser", "valider", "delete" });

		binder.registerCustomEditor(Set.class, "listGroup",
				new CustomCollectionEditor(Set.class) {
					protected Object convertElement(Object element) {
						if (element instanceof String) {
							Group g = groupeCache.get(Integer.parseInt(element
									.toString()));

							return g;
						}
						return null;
					}
				});
	}

	@ModelAttribute("lstGroupes")
	public List<Group> getGroups() {
		return groupService.getAllGroups();
	}

	@RequestMapping(value = "new", method = RequestMethod.GET)
	public String showForm(Model model) {

		lstGrp = groupService.getAllGroups();
		groupeCache = new HashMap<Integer, Group>();
		for (Group g : lstGrp) {
			groupeCache.put((Integer) g.getIdGroup(), g);
		}
		model.addAttribute("utilisateur", new UserFormAdmin());
		model.addAttribute("lstGroupes", lstGrp);
		return form_ajout;
	}

	@RequestMapping(value = "", method = RequestMethod.POST)
	public String postForm(
			@ModelAttribute("utilisateur") @Valid UserFormAdmin form,
			BindingResult result) {
		// Gestion erreur confirmation password and email

		convertPasswordError(result);

		// ajout database
		// first persist user, so add group
		userService.registerUser(form, form.getEmail(), form.getPassword(),
				result);
		return (result.hasErrors() ? form_ajout : db_ajout_confirm);
	}

	private static void convertPasswordError(BindingResult result) {
		for (ObjectError error : result.getGlobalErrors()) {
			String msg = error.getDefaultMessage();
			if ("account.password.mistmatch.message".equals(msg)) {
				if (!result.hasFieldErrors("password")) {
					result.rejectValue("password", "error.mistmatch");
				}
			}
		}
	}

	public UserDAO getUserRepository() {
		return userRepository;
	}

	public void setUserRepository(UserDAO userRepository) {
		this.userRepository = userRepository;
	}

	@RequestMapping(value = "/edit/{idUser}", method = RequestMethod.GET)
	public String editForm(Model model, @PathVariable Integer idUser) {
		User toto = userRepository.findById(idUser);
		lstGrp = groupService.getAllGroups();
		groupeCache = new HashMap<Integer, Group>();
		for (Group g : lstGrp) {
			groupeCache.put((Integer) g.getIdGroup(), g);
		}
		model.addAttribute("utilisateur", toto);
		model.addAttribute("lstGroupes", lstGrp);
		return form_edit;
	}

	@RequestMapping(value = "/edit/{idUser}", method = RequestMethod.POST)
	public String editingUser(HttpServletRequest request,
			@ModelAttribute("utilisateur") @Valid User user,
			BindingResult result, @PathVariable Integer idUser) {
		if (result.hasErrors()) {
			System.out.println(result.toString());
			return form_edit;
		}
		User u = userRepository.findById(idUser);
		user.setIdUser(u.getIdUser());
		user.setActivate(u.isActivate());
		user.setCodeVerif(u.getCodeVerif());
		user.setDateLastBadAttempt(u.getDateLastBadAttempt());
		user.setDateLastConnexion(u.getDateLastConnexion());
		user.setDateLimitCode(u.getDateLimitCode());
		user.setDateReactivate(u.getDateReactivate());
		user.setDateRegister(u.getDateRegister());
		user.setErrorConnection(u.getErrorConnection());
		user.setSrcAvatar(u.getSrcAvatar());
		userRepository.updateUser(user);

		return "redirect:../confirmationModification";
	}

	@RequestMapping(value = "/confirmationModification")
	public String confirmModif() {
		return db_modif_confirm;
	}

	@RequestMapping(value = "/list")
	public String viewList(Model model) {
		List<User> lstUsers = userRepository.getUsers();
		model.addAttribute("listUsers", lstUsers);
		return list_users;
	}

	@RequestMapping(value = "/Validation")
	public String viewListWaiting(Model model) {
		List<User> lstUsers = userRepository.getUsersWaitingValidation();
		model.addAttribute("nbUsers", lstUsers.size());
		model.addAttribute("listUsers", lstUsers);
		return list_users_validation;
	}

	@RequestMapping(value = "/valider/{idUser}", method = RequestMethod.GET)
	public String validUserForm(Model model, @PathVariable Integer idUser) {
		User toto = userRepository.findById(idUser);
		lstGrp = groupService.getAllGroups();
		groupeCache = new HashMap<Integer, Group>();
		for (Group g : lstGrp) {
			groupeCache.put((Integer) g.getIdGroup(), g);
		}
		model.addAttribute("utilisateur", toto);
		model.addAttribute("lstGroupes", lstGrp);
		return valid_user;
	}
	
	@RequestMapping(value = "/delete/{idUser}", method = RequestMethod.GET)
	public String actionDeleteUser(HttpServletRequest request, @PathVariable Integer idUser) {
		deleteUser(request,idUser);
		return "redirect:../list";
	}
	
	@RequestMapping(value = "/valider/{idUser}", method = RequestMethod.POST)
	public String validatingUser(HttpServletRequest request,
			@ModelAttribute("utilisateur") @Valid User user,
			BindingResult result, @PathVariable Integer idUser) {
		// option valider
		if (request.getParameter("valider") != null) {
			//group required before validation
			if (user.getListGroup() == null) {
				result.rejectValue("listGroup", "error.user.without.group");
			}
			if (result.hasErrors()) {
				System.out.println(result.toString());
				return valid_user;
			}	
			User u = userRepository.findById(idUser);
			u.getListGroup().clear();
			for (Group g : user.getListGroup()) {
				g = groupRepository.merge(g);
				u.addGroup(g);
				g.addUser(u);
			}
			u.setFirstName(user.getFirstName());
			u.setLastName(user.getLastName());
			u.setEmail(user.getEmail());
			u.setFonction(user.getFonction());
			u.setInstitution(user.getInstitution());
			u.setTel(user.getTel());
			u.setGsm(user.getGsm());
			u.setIsAdmin(user.isAdmin());
			validateUser( request,u);
		}
		// Delete: supprimer utilisateur
		else if (request.getParameter("delete") != null) {	
			deleteUser(request,idUser);
		}	
		return "redirect:../Validation";
	}

	private void validateUser(HttpServletRequest request,User toto) {
		// renommer avatar

		String oldName = toto.getSrcAvatar();
		if (oldName != null && !oldName.isEmpty()) {
			String avatarFolder = request
					.getSession()
					.getServletContext()
					.getRealPath(
							"/resources/upload/" + FileUtil.USER_AVATAR);
			String newName = String.valueOf(toto.getIdUser());
			toto.setSrcAvatar(FileUtil.renameFile(avatarFolder, newName,
					oldName));
		}
		toto.setActivate(true);
		userRepository.save(toto);

		// envoyer email
		Message msgDao = null;
		try {
			msgDao = messageService
					.findByTitle("email_confirmation_validation");
			Email.sendUserEmail(request.getSession().getServletContext(),
					"Pop Up validation de votre compte",
					msgDao.getMessage(), toto.getEmail());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private  void deleteUser(HttpServletRequest request,int idUser){
		//supprimer avatar
		User toto = userRepository.findById(idUser);
		String avatar= toto.getSrcAvatar();
		if (avatar != null && !avatar.isEmpty()) {
			String avatarFolder = request
					.getSession()
					.getServletContext()
					.getRealPath(
							"/resources/upload/" + FileUtil.USER_AVATAR);
    		File file = new File(avatarFolder+"/"+avatar);
    		 
    		if(file.delete()){
    			System.out.println(file.getName() + " is deleted!");
    		}else{
    			System.out.println("Delete operation is failed: "+file.getName());
    		}
		}	
		//delete user
		toto.getListGroup().clear();
		userRepository.save(toto);
		toto = userRepository.merge(toto);
		userRepository.delete(toto);
	}
}
